<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Vue 라우터 | Vue 테스팅 핸드북</title>
    <meta name="description" content="">
    <link rel="icon" href="https://lmiller1990.github.io/vue-testing-handbook/img/favicon.png">
  <meta property="og:title" content="Vue Testing Handbook">
  <meta property="og:description" content="Vue testing handbook">
  <meta property="og:type" content="website">
  <meta property="og:url" content="https://lmiller1990.github.io/vue-testing-handbook/">
  <meta property="og:image" content="https://lmiller1990.github.io/vue-testing-handbook/img/og.png">
    
    <link rel="preload" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css" as="style"><link rel="preload" href="/vue-testing-handbook/assets/js/app.14051834.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/3.119a321e.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/2.94957ecd.js" as="script"><link rel="preload" href="/vue-testing-handbook/assets/js/45.619b76a6.js" as="script"><link rel="prefetch" href="/vue-testing-handbook/assets/js/10.7b1750c8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/100.87c02eb0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/101.9f86f8af.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/102.7cf5b3b5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/103.9a447cc0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/104.d960f455.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/105.42aa8c19.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/106.fa067e24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/107.f6145328.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/108.4251a9d9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/109.6e04b4aa.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/11.c9a15d65.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/110.203be49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/111.e66d4c1a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/112.d5cf2637.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/113.0e1df8ea.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/114.b1d0a5f5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/115.d21ab6a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/116.e13d34ff.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/117.532bedf9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/118.b99c8d4d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/119.97666be8.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/12.8ec4d737.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/120.e5fbc47b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/121.2d6cedde.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/122.7dc3c3fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/123.82fcb804.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/124.affd46d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/125.10d1ddcb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/126.8ca1978a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/127.7b76e158.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/128.e0d8fdce.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/129.e861e49f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/13.96ee585a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/130.474092c4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/131.71e4509c.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/132.b48fe96d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/133.9268758a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/134.6a042ef6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/135.6df261f9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/136.8aab4165.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/137.60d15690.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/138.29f827fd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/139.e8db710e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/14.522b77b9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/140.8a3b2b26.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/141.cd5f96df.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/142.04a47072.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/143.ac0cb5e1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/144.c69a73ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/15.2f00de2d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/16.d120a376.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/17.9260e267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/18.4e3a9d5e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/19.bfe7cfa3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/20.52828530.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/21.4d92035b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/22.49a88bda.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/23.79de1f16.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/24.f45f108e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/25.48371e8a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/26.bc7a5470.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/27.49bfeced.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/28.b697055e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/29.0ef469da.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/30.bd209efe.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/31.ddf8aa10.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/32.95ec3267.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/33.52cf0ebc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/34.73b1ca03.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/35.be79f171.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/36.52a4dcd2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/37.a02e83c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/38.2a809ae1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/39.31de0194.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/4.a86536d1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/40.4a3cfcb7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/41.db485265.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/42.8c4375ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/43.2f241bb5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/44.43539973.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/46.00e17cc1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/47.faf51fac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/48.840de9e5.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/49.3410da74.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/5.d3ebdf21.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/50.647913c0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/51.4990b428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/52.85ff4209.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/53.7bbf915a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/54.1fc8316d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/55.374436d3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/56.40ebbbe6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/57.40d9cc46.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/58.37ab0bcf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/59.8df2efac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/6.637082cf.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/60.326b4bdd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/61.449fcfe0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/62.f05ac3d6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/63.e1723f7e.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/64.5b9e17ef.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/65.52e8ce24.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/66.cbdf653b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/67.522e5bfd.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/68.1c27735b.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/69.1f5624e9.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/7.43089f9d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/70.49fd6b50.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/71.20acc429.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/72.715f4620.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/73.ac123d7d.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/74.59a869d0.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/75.772485ad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/76.b887e73a.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/77.70e54ee3.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/78.2306c3e7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/79.e01a6cd1.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/8.4c4cdaa7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/80.c12fc82f.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/81.44ef90b7.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/82.ff3143a2.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/83.22084435.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/84.485c66f4.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/85.d8afef97.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/86.2ba55e96.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/87.d5642266.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/88.3ad1f8ac.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/89.e370d2fc.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/9.a0f31be6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/90.2c039dfb.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/91.2c1dd586.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/92.571cd8ae.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/93.b88ae6f6.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/94.16000348.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/95.79a96428.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/96.c86f8cad.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/97.bc1d6c91.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/98.34c6a547.js"><link rel="prefetch" href="/vue-testing-handbook/assets/js/99.e1174558.js">
    <link rel="stylesheet" href="/vue-testing-handbook/assets/css/0.styles.99f2ca3b.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/vue-testing-handbook/ko/" class="home-link router-link-active"><!----> <span class="site-name">Vue 테스팅 핸드북</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">다른 언어로 보기</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/vue-router.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/vue-router.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/vue-router.html" class="nav-link">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/vue-router.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/vue-router.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/vue-router.html" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/vue-router.html" class="nav-link router-link-exact-active router-link-active">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><a href="https://vuejs-course.com/" target="_blank"><img id="ad" src="https://raw.githubusercontent.com/lmiller1990/vue-testing-handbook/master/src/.vuepress/public/composition.png" alt="vuejs-course banner"></a> <br> <div class="info"><small>
    Hi! Get $10 off my
    <a href="https://vuejs-course.com/" target="_blank">new</a> <a href="https://vuejs-course.com/" target="_blank">course</a> <a href="https://vuejs-course.com/" target="_blank">on</a> <a href="https://vuejs-course.com/" target="_blank">Vue.js 3</a>,
    <a href="https://vuejs-course.com/" target="_blank">TypeScript and</a>,
    <a href="https://vuejs-course.com/" target="_blank">testing</a>,
    with the discount code VUEJS_COURSE_10_OFF.
    </small></div> <nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Select language" class="dropdown-title"><span class="title">다른 언어로 보기</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/vue-router.html" class="nav-link">English</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/vue-router.html" class="nav-link">v3</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ja/vue-router.html" class="nav-link">日本語</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ru/vue-router.html" class="nav-link">Русский (Vue.js 2)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/v3/ru/vue-router.html" class="nav-link">Русский (Vue.js 3)</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/zh-CN/vue-router.html" class="nav-link">简体中文</a></li><li class="dropdown-item"><!----> <a href="/vue-testing-handbook/ko/vue-router.html" class="nav-link router-link-exact-active router-link-active">한국어</a></li></ul></div></div> <a href="https://github.com/lmiller1990/vue-testing-handbook" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav>  <ul class="sidebar-links"><li><a href="/vue-testing-handbook/ko/" class="sidebar-link">환영합니다</a></li><li><a href="/vue-testing-handbook/ko/setting-up-for-tdd.html" class="sidebar-link">TDD를 위한 설정하기</a></li><li><a href="/vue-testing-handbook/ko/rendering-a-component.html" class="sidebar-link">컴포넌트 렌더하기</a></li><li><a href="/vue-testing-handbook/ko/components-with-props.html" class="sidebar-link">props 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/computed-properties.html" class="sidebar-link">computed 프로퍼티</a></li><li><a href="/vue-testing-handbook/ko/simulating-user-input.html" class="sidebar-link">사용자 입력 시연하기</a></li><li><a href="/vue-testing-handbook/ko/testing-emitted-events.html" class="sidebar-link">emitted 이벤트 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/mocking-global-objects.html" class="sidebar-link">전역 객체 모킹하기</a></li><li><a href="/vue-testing-handbook/ko/stubbing-components.html" class="sidebar-link">컴포넌트 스터빙</a></li><li><a href="/vue-testing-handbook/ko/finding-elements-and-components.html" class="sidebar-link">엘리먼트와 컴포넌트 찾기</a></li><li><a href="/vue-testing-handbook/ko/testing-vuex.html" class="sidebar-link">Vuex 테스트하기</a></li><li><a href="/vue-testing-handbook/ko/vuex-mutations.html" class="sidebar-link">Vuex - 뮤테이션</a></li><li><a href="/vue-testing-handbook/ko/vuex-actions.html" class="sidebar-link">Vuex - 액션</a></li><li><a href="/vue-testing-handbook/ko/vuex-getters.html" class="sidebar-link">Vuex - 게터</a></li><li><a href="/vue-testing-handbook/ko/vuex-in-components.html" class="sidebar-link">컴포넌트 내에 있는 Vuex - $state와 게터</a></li><li><a href="/vue-testing-handbook/ko/vuex-in-components-mutations-and-actions.html" class="sidebar-link">컴포넌트 내에 있는 Vuex - 뮤테이션과 액션</a></li><li><a href="/vue-testing-handbook/ko/vue-router.html" class="active sidebar-link">Vue 라우터</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#vue-라우터" class="sidebar-link">Vue 라우터</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#컴포넌트-생성하기" class="sidebar-link">컴포넌트 생성하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#라우터와-라우트-생성하기" class="sidebar-link">라우터와 라우트 생성하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#테스트-작성하기" class="sidebar-link">테스트 작성하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#mount를-사용하는-대형-렌더-트리를-위한-제-2의-해결책" class="sidebar-link">mount를 사용하는 대형 렌더 트리를 위한 제 2의 해결책</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#mock-라우터-사용하기" class="sidebar-link">Mock 라우터 사용하기</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#라우터-훅을-테스트하는-전략" class="sidebar-link">라우터 훅을 테스트하는 전략</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#전역-가드" class="sidebar-link">전역 가드</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#컴포넌트-가드" class="sidebar-link">컴포넌트 가드</a></li><li class="sidebar-sub-header"><a href="/vue-testing-handbook/ko/vue-router.html#결론" class="sidebar-link">결론</a></li></ul></li><li><a href="/vue-testing-handbook/ko/composition-api.html" class="sidebar-link">컴포지션 API</a></li><li><a href="/vue-testing-handbook/ko/reducing-boilerplate-in-tests.html" class="sidebar-link">보일러플레이트 줄이기</a></li><li><a href="/vue-testing-handbook/ko/jest-mocking-modules.html" class="sidebar-link">Jest - 모듈 모킹하기</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="vue-라우터"><a href="#vue-라우터" class="header-anchor">#</a> Vue 라우터</h2> <p>라우터가 보통 함께 작동하는 여러 컴포넌트를 포함하다 보니, 종종 라우팅 테스트는 e2e/통합 테스트 수준 같은 <a href="https://www.freecodecamp.org/news/the-front-end-test-pyramid-rethink-your-testing-3b343c2bca51/" target="_blank" rel="noopener noreferrer">testing pyramid<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 위에서 진행됩니다. 하지만 라우팅에 대한 몇 가지 유닛 테스트를 하는 것도 도움이 될 수 있습니다.</p> <p>이전 세션에서 얘기했던 것과 비슷하게, 라우터와 상호 작용하는 컴포넌트를 테스트하는 두 가지 방법이 있습니다.</p> <ol><li>실제 라우터 인스턴스 사용하기</li> <li><code>$route</code>와 <code>$router</code> 글로벌 객체 모킹하기</li></ol> <p>대부분의 Vue 어플리케이션이 공식 Vue 라우터를 사용하기 때문에, 이 가이드는 거기에 초점을 맞추겠습니다.</p> <p>이 페이지에서 설명한 테스트의 소스 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/App.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>와 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/NestedRoute.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>에서 찾을 수 있습니다.</p> <h2 id="컴포넌트-생성하기"><a href="#컴포넌트-생성하기" class="header-anchor">#</a> 컴포넌트 생성하기</h2> <p><code>/nested-child</code> 라우트를 가진 간단한 <code>&lt;App&gt;</code>을 만들어보겠습니다.  <code>/nested-child</code>에 방문하면 <code>&lt;NestedRoute&gt;</code> 컴포넌트를 렌더합니다.  <code>App.vue</code> 파일을 생성하고 아래의 축소된 컴포넌트를 삽입하겠습니다.</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>app<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-view</span> <span class="token punctuation">/&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">'app'</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p><code>&lt;NestedRoute&gt;</code>도 아래와 같이 축소된 형태입니다.</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>Nested Route<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">&quot;NestedRoute&quot;</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h2 id="라우터와-라우트-생성하기"><a href="#라우터와-라우트-생성하기" class="header-anchor">#</a> 라우터와 라우트 생성하기</h2> <p>이제 테스트할 몇 가지 라우트가 필요합니다. 라우트부터 시작하겠습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> NestedRoute <span class="token keyword">from</span> <span class="token string">&quot;@/components/NestedRoute.vue&quot;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span> path<span class="token punctuation">:</span> <span class="token string">&quot;/nested-route&quot;</span><span class="token punctuation">,</span> component<span class="token punctuation">:</span> NestedRoute <span class="token punctuation">}</span>
<span class="token punctuation">]</span>
</code></pre></div><p>실제 앱에서는 보통 <code>router.js</code> 파일을 생성하고 작성한 라우트를 import 합니다. 그리고 아래와 같이 작성합니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">&quot;vue&quot;</span>
<span class="token keyword">import</span> VueRouter <span class="token keyword">from</span> <span class="token string">&quot;vue-router&quot;</span>
<span class="token keyword">import</span> routes <span class="token keyword">from</span> <span class="token string">&quot;./routes.js&quot;</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> routes <span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>테스트에서 <code>Vue.use(...)</code>를 호출해서 전역 네임스페이스를 오염시키고 싶지는 않기 때문에, 테스트의 test basis로 사용할 라우터를 생성하겠습니다. 생성한 라우터는 유닛 테스트를 진행하는 동안 앱의 상태를 좀 더 유연하게 통제할 수 있도록 해줄 것입니다.</p> <h2 id="테스트-작성하기"><a href="#테스트-작성하기" class="header-anchor">#</a> 테스트 작성하기</h2> <p>몇 가지 코드를 보고 나서, 어떤 일인지에 관해 얘기해보겠습니다.  <code>App.vue</code>를 테스트하고 있고, <code>App.spec.js</code>에 아래의 내용을 추가합니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> shallowMount<span class="token punctuation">,</span> mount<span class="token punctuation">,</span> createLocalVue <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@vue/test-utils&quot;</span>
<span class="token keyword">import</span> App <span class="token keyword">from</span> <span class="token string">&quot;@/App.vue&quot;</span>
<span class="token keyword">import</span> VueRouter <span class="token keyword">from</span> <span class="token string">&quot;vue-router&quot;</span>
<span class="token keyword">import</span> NestedRoute <span class="token keyword">from</span> <span class="token string">&quot;@/components/NestedRoute.vue&quot;</span>
<span class="token keyword">import</span> routes <span class="token keyword">from</span> <span class="token string">&quot;@/routes.js&quot;</span>

<span class="token keyword">const</span> localVue <span class="token operator">=</span> <span class="token function">createLocalVue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
localVue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&quot;App&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;라우팅을 통해서 자식 컴포넌트를 렌더한다&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> routes <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>App<span class="token punctuation">,</span> <span class="token punctuation">{</span> 
      localVue<span class="token punctuation">,</span>
      router
    <span class="token punctuation">}</span><span class="token punctuation">)</span>

    router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">&quot;/nested-route&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span><span class="token function">$nextTick</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span>NestedRoute<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">exists</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><ul><li>테스트에 <code>await</code>을 표시하고 <code>nextTick</code>을 호출한 것을 주목하세요. 그 이유에 대한 자세한 설명은 <a href="/vue-testing-handbook/simulating-user-input.html#writing-the-test">여기</a>에서 볼 수 있습니다.</li></ul> <p>평상시처럼 테스트를 위한 다양한 모듈을 import 하면서 시작합니다. 두드러지는 부분은 애플리케이션에서 사용할 실제 라우트를 추출하고 있는 것입니다. 이 방법은 다음과 같은 부분에서 이상적입니다. 실제 라우팅이 망가진다면, 유닛 테스트는 실패할 것이고, 애플리케이션을 배포하기 전에 해당 문제를 고칠 수 있습니다.</p> <p>모든 <code>&lt;App&gt;</code> 테스트에서 같은 <code>localVue</code>를 사용할 수 있습니다. 그래서 localVue는 처음 <code>describe</code> 블록 밖에서 선언됩니다. 그렇지만, 다른 라우트에 대한 테스트를 하고 싶을지도 모르기 때문에, 라우터는 <code>it</code> 블록 내에서 정의돼야 합니다.</p> <p>여기서 이 문서에 있는 다른 가이드와 구별되는 주목할만한 부분은 <code>shallowMount</code> 대신 <code>mount</code>를 사용하고 있다는 점입니다. <code>shallowMount</code>를 사용한다면 현재 라우트와 무관하게, <code>&lt;router-link&gt;</code>는 스텁(stub)되지 않을 것입니다. 그리고 쓸모없는 스텁 컴포넌트가 렌더될 것입니다.</p> <h2 id="mount를-사용하는-대형-렌더-트리를-위한-제-2의-해결책"><a href="#mount를-사용하는-대형-렌더-트리를-위한-제-2의-해결책" class="header-anchor">#</a> <code>mount</code>를 사용하는 대형 렌더 트리를 위한 제 2의 해결책</h2> <p><code>mount</code>를 사용하면 몇 가지 경우에는 괜찮을 수 있습니다. 그러나 때로는 적합한 방법이 아닙니다. 예를 들어 여러분이 전체 <code>&lt;App&gt;</code> 컴포넌트를 렌더하고 있고, <App> 컴포넌트가 자식 컴포넌트와 기타 등등을 포함한 많은 컴포넌트를 포함하는 대형 렌더 트리를 지닌다고 가정해보겠습니다. 많은 자식 컴포넌트가 다양한 라이프사이클 훅을 유발하고, API 요청 같은 것들을 하고 있습니다.</App></p> <p>Jest를 사용하고 있다면, Jest의 강력한 모킹 시스템은 이 문제를 해결하는 훌륭한 해결책을 제공합니다. <code>&lt;NestedRoute&gt;</code>의 경우에는 간단하게 자식 컴포넌트를 mock 할 수 있습니다. 아래의 mock을 사용할 수 있고, 위 테스트는 여전히 통과합니다.</p> <div class="language-js extra-class"><pre class="language-js"><code>jest<span class="token punctuation">.</span><span class="token function">mock</span><span class="token punctuation">(</span><span class="token string">&quot;@/components/NestedRoute.vue&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">&quot;NestedRoute&quot;</span><span class="token punctuation">,</span>
  <span class="token function-variable function">render</span><span class="token punctuation">:</span> <span class="token parameter">h</span> <span class="token operator">=&gt;</span> <span class="token function">h</span><span class="token punctuation">(</span><span class="token string">&quot;div&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="mock-라우터-사용하기"><a href="#mock-라우터-사용하기" class="header-anchor">#</a> Mock 라우터 사용하기</h2> <p>때로는 실제 라우터가 불필요합니다. 현재 path의 쿼리 스트링(query string)을 바탕으로 username을 보여주도록 <code>&lt;NestedRoute&gt;</code>를 업데이트하겠습니다. 이번에는 기능을 구현하기 위해 TDD를 사용하겠습니다. 아래에 간단하게 컴포넌트를 렌더하고 어설션(assertion)을 하는 기본적인 테스트가 있습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> shallowMount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@vue/test-utils&quot;</span>
<span class="token keyword">import</span> NestedRoute <span class="token keyword">from</span> <span class="token string">&quot;@/components/NestedRoute.vue&quot;</span>
<span class="token keyword">import</span> routes <span class="token keyword">from</span> <span class="token string">&quot;@/routes.js&quot;</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&quot;NestedRoute&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;쿼리 스트링으로부터 username을 렌더한다&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> username <span class="token operator">=</span> <span class="token string">&quot;alice&quot;</span>
    <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">shallowMount</span><span class="token punctuation">(</span>NestedRoute<span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;.username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>아직 <code>&lt;div class=&quot;username&quot;&gt;</code>이 없어서, 테스트를 실행하면 아래와 같은 메시지가 나옵니다.</p> <div class="language- extra-class"><pre class="language-text"><code>FAIL  tests/unit/NestedRoute.spec.js
  NestedRoute
    ✕ renders a username from query string (25ms)

  ● NestedRoute › renders a username from query string

    [vue-test-utils]: find did not return .username, cannot call text() on empty Wrapper
</code></pre></div><p><code>&lt;NestedRoute&gt;</code>를 업데이트하겠습니다.</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">&gt;</span></span>
    Nested Route
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
      {{ $route.params.username }}
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>이제 테스트가 실패하고 아래와 같은 메시지가 나옵니다.</p> <div class="language- extra-class"><pre class="language-text"><code>FAIL  tests/unit/NestedRoute.spec.js
  NestedRoute
    ✕ renders a username from query string (17ms)

  ● NestedRoute › renders a username from query string

    TypeError: Cannot read property 'params' of undefined
</code></pre></div><p><code>$route</code>가 존재하지 않기 때문입니다. 실제 라우터를 사용하고 있지만, 이 경우에는 그냥 <code>mocks</code> 마운팅 옵션을 사용하는 게 더 쉽습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;쿼리 스트링으로부터 username을 렌더한다&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> username <span class="token operator">=</span> <span class="token string">&quot;alice&quot;</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">shallowMount</span><span class="token punctuation">(</span>NestedRoute<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    mocks<span class="token punctuation">:</span> <span class="token punctuation">{</span>
      $route<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        params<span class="token punctuation">:</span> <span class="token punctuation">{</span> username <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token string">&quot;.username&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>이제 테스트가 통과합니다. 이 경우에 임의의 네비게이션이나 라우터의 구현체에 의존하는 어떤 것도 하고 싶지 않습니다. 그래서 <code>mocks</code>를 사용하는 것이 좋습니다. <code>username</code>이 쿼리 스트링에서 어떻게 오는지는 별로 신경 쓰지 않습니다. 단지 <code>username</code>이 존재할 뿐입니다.</p> <p>보통은 Vue 라우터로 클라이언트 사이드 렌더링을 하는 것이 아니라, 서버가 라우팅을 제공할 것입니다. 이런 경우에는 테스트에서 쿼리 스트링을 설정하는 <code>mocks</code>를 사용하는 것이 Vue 라우터의 실제 인스턴스를 사용하는 좋은 대안입니다.</p> <h2 id="라우터-훅을-테스트하는-전략"><a href="#라우터-훅을-테스트하는-전략" class="header-anchor">#</a> 라우터 훅을 테스트하는 전략</h2> <p>Vue 라우터는 <a href="https://router.vuejs.org/guide/advanced/navigation-guards.html" target="_blank" rel="noopener noreferrer">'navigation guards'<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>라고 불리는 몇 가지 타입의 라우터 훅을 제공합니다. 아래에 두 가지 예시가 있습니다.</p> <ol><li>전역 가드 ( <code>router.beforeEach</code> ). 라우터 인스턴에서 선언.</li> <li><code>beforeRouteEnter</code>같은 컴포넌트 가드. 컴포넌트에서 선언.</li></ol> <p>이런 훅이 올바르게 작동하는지 확인하는 것은 보통 통합 테스트의 일입니다. 한 라우트에서 또 다른 라우트로 사용자를 이동시키는 일이 필요하기 때문입니다. 하지만 네비게이션 가드에서 호출된 함수가 올바르게 작동하는지 알기 위해 유닛 테스트를 사용할 수 있고, 잠재적인 버그에 대해 빠른 피드백을 얻을 수 있습니다. 여기에 네비게이션 가드로부터 로직을 분리하고, 분리한 로직에 대해 유닛 테스트를 작성하는 몇 가지 전략이 있습니다.</p> <h2 id="전역-가드"><a href="#전역-가드" class="header-anchor">#</a> 전역 가드</h2> <p><code>shouldBustCache</code> 메타 필드를 포함하는 모든 라우트에서 호출하는 <code>bustCache</code> 함수를 가진다고 해보겠습니다. 여러분의 라우트는 아래와 같은 모습일 것입니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> NestedRoute <span class="token keyword">from</span> <span class="token string">&quot;@/components/NestedRoute.vue&quot;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    path<span class="token punctuation">:</span> <span class="token string">&quot;/nested-route&quot;</span><span class="token punctuation">,</span>
    component<span class="token punctuation">:</span> NestedRoute<span class="token punctuation">,</span>
    meta<span class="token punctuation">:</span> <span class="token punctuation">{</span>
      shouldBustCache<span class="token punctuation">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">]</span>
</code></pre></div><p>사용자가 오래된 데이터를 가지지 않도록, <code>shouldBustCache</code> 메타 필드를 사용해서 현재 데이터를 무효화하기를 원합니다. 구현체는 아래와 같습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> Vue <span class="token keyword">from</span> <span class="token string">&quot;vue&quot;</span>
<span class="token keyword">import</span> VueRouter <span class="token keyword">from</span> <span class="token string">&quot;vue-router&quot;</span>
<span class="token keyword">import</span> routes <span class="token keyword">from</span> <span class="token string">&quot;./routes.js&quot;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> bustCache <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;./bust-cache.js&quot;</span>

Vue<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>VueRouter<span class="token punctuation">)</span>

<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VueRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> routes <span class="token punctuation">}</span><span class="token punctuation">)</span>

router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span><span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>matched<span class="token punctuation">.</span><span class="token function">some</span><span class="token punctuation">(</span><span class="token parameter">record</span> <span class="token operator">=&gt;</span> record<span class="token punctuation">.</span>meta<span class="token punctuation">.</span>shouldBustCache<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">bustCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> router
</code></pre></div><p>여러분의 유닛 테스트에서, 라우터 인스턴스를 추출하거나, <code>router.beforeHooks[0]()</code>을 입력해서 <code>beforeEach</code>를 호출하려고 시도 <strong>할 수도</strong> 있습니다. 이 방법은  <code>next</code>에 대한 에러를 던집니다. 올바른 인자를 넘기지 않았기 때문입니다. 이 방법 대신에 할 수 있는 한 가지 전략은, 라우터에 연결하기 전에 <code>beforeEach</code> 네비게이션 훅을 분리하고 독립적으로 내보내는 것입니다. 아래와 같은 방법입니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span><span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>to<span class="token punctuation">.</span>matched<span class="token punctuation">.</span><span class="token function">some</span><span class="token punctuation">(</span><span class="token parameter">record</span> <span class="token operator">=&gt;</span> record<span class="token punctuation">.</span>meta<span class="token punctuation">.</span>shouldBustCache<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">bustCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

router<span class="token punctuation">.</span><span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span><span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function">beforeEach</span><span class="token punctuation">(</span>to<span class="token punctuation">,</span> <span class="token keyword">from</span><span class="token punctuation">,</span> next<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> router
</code></pre></div><p>약간 길어졌지만, 이제 테스트를 작성하는 일이 쉬워졌습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span> beforeEach <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@/router.js&quot;</span>
<span class="token keyword">import</span> mockModule <span class="token keyword">from</span> <span class="token string">&quot;@/bust-cache.js&quot;</span>

jest<span class="token punctuation">.</span><span class="token function">mock</span><span class="token punctuation">(</span><span class="token string">&quot;@/bust-cache.js&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> bustCache<span class="token punctuation">:</span> jest<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">&quot;beforeEach&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token function">afterEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    mockModule<span class="token punctuation">.</span>bustCache<span class="token punctuation">.</span><span class="token function">mockClear</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;/user로 이동할 때 캐시를 없앤다&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> to <span class="token operator">=</span> <span class="token punctuation">{</span>
      matched<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> meta<span class="token punctuation">:</span> <span class="token punctuation">{</span> shouldBustCache<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">const</span> next <span class="token operator">=</span> jest<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token function">beforeEach</span><span class="token punctuation">(</span>to<span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> next<span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>mockModule<span class="token punctuation">.</span>bustCache<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;/user로 이동할 때 캐시를 없애지 않는다&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> to <span class="token operator">=</span> <span class="token punctuation">{</span>
      matched<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> meta<span class="token punctuation">:</span> <span class="token punctuation">{</span> shouldBustCache<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">const</span> next <span class="token operator">=</span> jest<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token function">beforeEach</span><span class="token punctuation">(</span>to<span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> next<span class="token punctuation">)</span>

    <span class="token function">expect</span><span class="token punctuation">(</span>mockModule<span class="token punctuation">.</span>bustCache<span class="token punctuation">)</span><span class="token punctuation">.</span>not<span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token function">expect</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>관심사의 요점은 <code>jest.mock</code>을 사용해서 전체 모듈을 mock 하고, <code>afterEach</code>훅을 사용해서 mock을 재설정하는 것입니다.  <code>beforeEach</code>를 분리하여, 일반 자바스크립트 함수로 내보내면, 테스트가 쉬워집니다.</p> <p>훅이 실제로 <code>bustCache</code>를 호출하고 있고, 가장 최근 데이터를 보여주고 있는 것을 확인하기 위해서, <a href="https://www.cypress.io/" target="_blank" rel="noopener noreferrer">Cypress.io<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 같은 e2e 테스팅 툴을 사용할 수 있습니다. 그리고 Cypress.io는 vue-cli를 사용하면 애플리케이션에 포함된 채로 제공됩니다.</p> <h2 id="컴포넌트-가드"><a href="#컴포넌트-가드" class="header-anchor">#</a> 컴포넌트 가드</h2> <p>일반 자바스크립트 함수로 분리해서 본다면, 컴포넌트 가드도 테스트하기 쉽습니다. <code>&lt;NestedRoute&gt;</code>에 <code>beforeRouteLeave</code> 훅을 추가해보겠습니다.</p> <div class="language-vue extra-class"><pre class="language-vue"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
<span class="token keyword">import</span> <span class="token punctuation">{</span> bustCache <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@/bust-cache.js&quot;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
  name<span class="token punctuation">:</span> <span class="token string">&quot;NestedRoute&quot;</span><span class="token punctuation">,</span>

  <span class="token function">beforeRouteLeave</span><span class="token punctuation">(</span><span class="token parameter">to<span class="token punctuation">,</span> <span class="token keyword">from</span><span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">bustCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>전역 가드와 정확하게 같은 방법으로 테스트할 수 있습니다.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// ...</span>
<span class="token keyword">import</span> NestedRoute <span class="token keyword">from</span> <span class="token string">&quot;@/components/NestedRoute.vue&quot;</span>
<span class="token keyword">import</span> mockModule <span class="token keyword">from</span> <span class="token string">&quot;@/bust-cache.js&quot;</span>

jest<span class="token punctuation">.</span><span class="token function">mock</span><span class="token punctuation">(</span><span class="token string">&quot;@/bust-cache.js&quot;</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">(</span><span class="token punctuation">{</span> bustCache<span class="token punctuation">:</span> jest<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token function">it</span><span class="token punctuation">(</span><span class="token string">&quot;라우트를 떠날 때 bustCache와 next를 호출한다&quot;</span><span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">shallowMount</span><span class="token punctuation">(</span>NestedRoute<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> next <span class="token operator">=</span> jest<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  NestedRoute<span class="token punctuation">.</span><span class="token function">beforeRouteLeave</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> next<span class="token punctuation">)</span>
  <span class="token keyword">await</span> wrapper<span class="token punctuation">.</span>vm<span class="token punctuation">.</span><span class="token function">$nextTick</span><span class="token punctuation">(</span><span class="token punctuation">)</span>


  <span class="token function">expect</span><span class="token punctuation">(</span>mockModule<span class="token punctuation">.</span>bustCache<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token function">expect</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toHaveBeenCalled</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>이런 방식의 유닛 테스트가 개발하는 동안 즉각적인 피드백을 받는 데 도움을 줄 수 있습니다. 라우터와 네비게이션 훅이 종종 어떤 효과를 얻기 위해서 몇 가지 컴포넌트와 상호작용하기 때문입니다. 모든 것이 기대한 것처럼 잘 작동하는지 확인하기 위해서 통합 테스트를 할 수도 있습니다.</p> <h2 id="결론"><a href="#결론" class="header-anchor">#</a> 결론</h2> <p>이 가이드는 아래의 내용을 다뤘습니다.</p> <ul><li>Vue 라우터에 의해 조건부로 렌더된 컴포넌트 테스트하기</li> <li><code>jest.mock</code>과 <code>localVue</code>를 사용해서 Vue 컴포넌트 모킹하기</li> <li>라우터로부터 전역 네비게이션 가드를 분리하고 독립적으로 테스트하기</li> <li>모듈을 mock 하기 위해서 <code>jest.mcok</code> 사용하기</li></ul> <p>이 페이지에서 설명한 테스트의 소스 코드는 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/App.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>와 <a href="https://github.com/lmiller1990/vue-testing-handbook/tree/master/demo-app/tests/unit/NestedRoute.spec.js" target="_blank" rel="noopener noreferrer">여기<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>에서 찾을 수 있습니다.</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/lmiller1990/vue-testing-handbook/edit/master/ko/vue-router.md" target="_blank" rel="noopener noreferrer">Github에서 이 페이지 수정하기</a> <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></div> <div class="last-updated"><span class="prefix">마지막 업데이트:</span> <span class="time">2020. 2. 2. 오전 12:39:11</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/vue-testing-handbook/ko/vuex-in-components-mutations-and-actions.html" class="prev">컴포넌트 내에 있는 Vuex - 뮤테이션과 액션</a></span> <span class="next"><a href="/vue-testing-handbook/ko/composition-api.html">컴포지션 API</a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/vue-testing-handbook/assets/js/app.14051834.js" defer></script><script src="/vue-testing-handbook/assets/js/3.119a321e.js" defer></script><script src="/vue-testing-handbook/assets/js/2.94957ecd.js" defer></script><script src="/vue-testing-handbook/assets/js/45.619b76a6.js" defer></script>
  </body>
</html>
